package com.zk.shopping.base.service.impl;

import com.zk.shopping.base.model.KeyValue;
import com.zk.shopping.base.model.ModelResult;
import com.zk.shopping.base.model.ReturnCodeEnum;
import com.zk.shopping.base.service.ISecurityService;
import com.zk.shopping.base.utils.Constants;
import com.zk.shopping.base.utils.RSAUtils;
import com.zk.shopping.base.utils.RedisClientUtils;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import org.springframework.stereotype.Service;

/**
 *
 * 安全相关的服务
 * Created by zhangkai on 3/30/16.
 */
@Service
public class SecurityServiceImpl implements ISecurityService {

    @Override
    public ModelResult<RSAPublicKey> getRSAPublicKey(String signKey){
        ModelResult<RSAPublicKey> result = new ModelResult<>("创建成功");
        try {
            RSAPublicKey rsaPublic;
            if(RedisClientUtils.exists(Constants.REDIS_RSA_KEY_PAIRS_MODULUS + signKey)) {
                String modulus = RedisClientUtils.get(Constants.REDIS_RSA_KEY_PAIRS_MODULUS + signKey);
                String publicExponent = RedisClientUtils.get(Constants.REDIS_RSA_KEY_PAIRS_EXPONENT_PUBLIC + signKey);
                rsaPublic = RSAUtils.getPublicKey(new BigInteger(modulus), new BigInteger(publicExponent));
            }else{
                KeyValue<RSAPublicKey, RSAPrivateKey> rsaKeyPair = RSAUtils.getKeys();
                rsaPublic = rsaKeyPair.getKey();
                RSAPrivateKey rsaPrivate = rsaKeyPair.getValue();
                RedisClientUtils.setex(Constants.REDIS_RSA_KEY_PAIRS_MODULUS + signKey, 60, String.valueOf(rsaPrivate.getModulus()));
                RedisClientUtils.setex(Constants.REDIS_RSA_KEY_PAIRS_EXPONENT_PRIVATE + signKey, 60, String.valueOf(rsaPrivate.getPrivateExponent()));
                RedisClientUtils.setex(Constants.REDIS_RSA_KEY_PAIRS_EXPONENT_PUBLIC + signKey, 60, String.valueOf(rsaPublic.getPublicExponent()));
            }
            result.setData(rsaPublic);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            result.setCode(1);
            result.setMessage("生成公钥失败");
        }
        return result;
    }

    @Override
    public ModelResult<RSAPrivateKey> getRSAPrivateKey(String signKey) {
        ModelResult<RSAPrivateKey> result = new ModelResult<>("获取成功");
        if(!RedisClientUtils.exists(Constants.REDIS_RSA_KEY_PAIRS_MODULUS + signKey)){
            result.setCode(1);
            result.setMessage("未找到对应的密钥");
        }else{
            String modulus = RedisClientUtils.get(Constants.REDIS_RSA_KEY_PAIRS_MODULUS + signKey);
            String privateExponent = RedisClientUtils.get(Constants.REDIS_RSA_KEY_PAIRS_EXPONENT_PRIVATE + signKey);
            RSAPrivateKey privateKey = RSAUtils.getPrivateKey(new BigInteger(modulus), new BigInteger(privateExponent));
            result.setData(privateKey);
        }
        return result;
    }

    @Override
    public ModelResult<String> encrypt4RSA(String signKey, String data){
        ModelResult<String> result = new ModelResult<>("加密成功");
        ModelResult<RSAPublicKey> rsaPublicKeyResult = getRSAPublicKey(signKey);
        if(rsaPublicKeyResult.getCode() != ReturnCodeEnum.REQUEST_SUCESS.code){
            result.setCode(1);
            result.setMessage("找不到公钥");
            return result;
        }
        RSAPublicKey rsaPublicKey = rsaPublicKeyResult.getData();
        try {
            String encryptData = RSAUtils.encryptByPublicKey(data, rsaPublicKey);
            result.setData(encryptData);
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(2);
            result.setMessage("加密失败");
        }
        return  result;
    }

    @Override
    public ModelResult<String> decrypt4RSA(String signKey, String data){
        ModelResult<String> result = new ModelResult<>("解密成功");
        ModelResult<RSAPrivateKey> rsaPrivateKeyResult = getRSAPrivateKey(signKey);
        if(rsaPrivateKeyResult.getCode() != ReturnCodeEnum.REQUEST_SUCESS.code){
            result.setCode(1);
            result.setMessage("找不到密钥");
            return result;
        }
        RSAPrivateKey rsaPrivateKey = rsaPrivateKeyResult.getData();
        try {
            String encryptData = RSAUtils.decryptByPrivateKey(data, rsaPrivateKey);
            result.setData(encryptData);
        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(2);
            result.setMessage("加密失败");
        }
        return  result;
    }
}
